package Getopt::Moose;

use if $ENV{DEBUG} => 'Smart::Comments';

use Moose;


# Pluggined Getopt::Moose parser
has 'parser' => (
    is => 'rw',
    isa => 'Getopt::Moose::Parser',
    default => sub { Getopt::Moose::Parser->new },
    handles => [ 'value', 'argv', 'argv_extra', 'options', 'status', 'warning' ],
);

# Filter for classes which are searched for getopt trait
has 'classes_filter' => (
    is => 'rw',
    isa => 'CodeRef',
    default => sub { sub { 1 } },
);

# Original @ARGV values
has 'argv' => (
    is => 'rw',
    isa => 'ArrayRef[Str]',
    auto_deref => 1,
    default => sub { [ @ARGV ] },
);

# Unrecognized @ARGV values
has 'argv_extra' => (
    is => 'rw',
    isa => 'ArrayRef[Str]',
    auto_deref => 1,
    default => sub { [] },
);

# Hash with options parsed from argv
has 'options' => (
    is => 'rw',
    isa => 'HashRef',
    auto_deref => 1,
    default => sub { {} },
);

# Status of parser
has 'status' => (
    is => 'rw',
    isa => 'Bool',
);

# Warnings collected by parser
has 'warning' => (
    is => 'rw',
    isa => 'Str',
    default => '',
);


sub BUILD {
    ### Getopt::Moose::BUILD : @_
    my ($self, $args) = @_;

    $self->get_options;
};


sub get_options {
    my ($self) = @_;

    my @attrs = $self->_compute_getopt_attributes;
    ### Getopt::Moose::get_options @attrs -> name : map { $_->name } @attrs

    return $self->parser->get_options($self, @attrs);
}


sub _compute_getopt_attributes {
    my ($self) = @_;

    my @classes = grep { $self->classes_filter->() }
                  grep { $_->isa('Moose::Object') && $_->does('Getopt::Moose::Role') }
                  Class::MOP->get_all_metaclasses;
    ### Getopt::Moose::_compute_getopt_attributes @classes : @classes

    my @attrs = grep { $_->does('Getopt::Moose::Meta::Attribute') }
                map { $_->meta->compute_all_applicable_attributes }
                @classes;
    ### Getopt::Moose::_compute_getopt_attributes @attrs->name : map { $_->name } @attrs

    return @attrs;
};


1;
